const express = require('express');
const { Op } = require('sequelize');
const router = express.Router();
const { User } = require('../../models');
const { success, failure } = require('../../utils/responses');
const { NotFound, BadRequest } = require('http-errors');
const bcrypt = require('bcryptjs');

/**
 * 公共方法：白名单过滤
 * @param req
 * @returns {{password, role: (number|string|*), introduce: ({type: *}|*), sex: ({allowNull: boolean, type: *, validate: {notNull: {msg: string}, notEmpty: {msg: string}, isIn: {args: [number[]], msg: string}}}|{defaultValue: number, allowNull: boolean, type: *}|*), nickname: (string|*), company: ({type: *}|*), avatar: ({type: *, validate: {isUrl: {msg: string}}}|*), email: (string|*), username}}
 */
const filterBody = (req) => {
  return {
    email: req.body.email,
    username: req.body.username,
    password: req.body.password,
    nickname: req.body.nickname,
    sex: req.body.sex,
    company: req.body.company,
    introduce: req.body.introduce,
    role: req.body.role,
    avatar: req.body.avatar,
  };
};

/**
 * 公共方法：查询当前用户
 */
const getUser = async (req, showPassword = false) => {
  // 获取用户 ID
  let id = req.user.id;

  let condition = {};
  if (!showPassword) {
    id = req.params.id;
    condition = {
      attributes: { exclude: ['password'] },
    };
  }
  // 查询当前用户
  const user = await User.findByPk(id, condition);

  // 如果没有找到，就抛出异常
  if (!user) {
    throw new NotFound(`ID: ${id}的用户未找到`);
  }

  return user;
};

/**
 * 查询用户列表
 * GET /admin/users
 */
router.get('/', async (req, res) => {
  try {
    const query = req.query;

    // 当前是第几页，如果不传，那就是第一页
    const currentPage = Math.abs(Number(query.current)) || 1;
    // 每页显示多少条数据，如果不传，那就显示10条
    const pageSize = Math.abs(Number(query.pageSize)) || 10;
    // 计算 offset
    const offset = (currentPage - 1) * pageSize;

    const condition = {
      attributes: { exclude: ['password'] },
      order: [['id', 'DESC']],
      limit: pageSize,
      offset,
      where: {},
    };
    if (query.email) {
      condition.where.email = query.email;
    }
    if (query.username) {
      condition.where.username = query.username;
    }
    if (query.nickname) {
      condition.where.nickname = {
        [Op.like]: `%${query.nickname}%`,
      };
    }
    if (query.role) {
      condition.where.role = query.role;
    }
    // 查询数据
    const { count, rows } = await User.findAndCountAll(condition);

    success(res, '查询用户列表成功', {
      data: rows,
      total: count,
    });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 查询当前登录的用户详情
 * GET /admin/users/info
 */
router.get('/info', async (req, res) => {
  try {
    const user = req.user;
    delete user.dataValues.password;
    success(res, '查询当前用户信息成功。', user);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 创建用户
 * GPOST /admin/users/add
 */
router.post('/add', async (req, res) => {
  try {
    // 创建用户
    const user = await User.create(filterBody(req));
    success(res, '创建用户成功', { data: user }, 201);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 更新用户密码
 * PUT /admin/users/password
 */
router.put('/password', async (req, res) => {
  const { password, newPassword, newPasswordConfirm } = req.body;
  try {
    if (!password) {
      throw new BadRequest('当前密码必须填写。');
    }

    if (newPassword !== newPasswordConfirm) {
      throw new BadRequest('两次输入的密码不一致。');
    }

    // 加上 true 参数，可以查询到加密后的密码
    const user = await getUser(req, true);
    // 验证当前密码是否正确
    const isPasswordValid = bcrypt.compareSync(password, user.password);
    console.log('isPasswordValid', isPasswordValid);
    if (!isPasswordValid) {
      throw new BadRequest('当前密码不正确。');
    }

    await user.update({ password: newPassword });

    // 删除密码
    delete user.dataValues.password;
    success(res, '更新账户信息成功。', { user });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 更新用户
 * PUT /admin/users/:id
 */
router.put('/:id', async (req, res) => {
  try {
    const user = await getUser(req);
    // 更新用户
    const updateUser = await user.update(filterBody(req));
    success(res, '更新用户成功', updateUser);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 查询用户详情
 * GET /admin/users/:id
 */
router.get('/:id', async (req, res) => {
  try {
    // 查询数据
    const user = await getUser(req);
    success(res, '查询用户详情成功', { data: user });
  } catch (error) {
    failure(res, error);
  }
});
module.exports = router;
